/*
求把 N×M 的棋盘分割成若干个 1×2 的长方形，有多少种方案。
例如：
- 当 N=2，M=4 时，共有 5 种方案。
- 当 N=2，M=3 时，共有 3 种方案。

输入格式
输入包含多组测试用例。
每组测试用例占一行，包含两个整数 N 和 M。
当输入用例 N=0，M=0 时，表示输入终止，且该用例无需处理。

输出格式
每个测试用例输出一个结果，每个结果占一行。

数据范围
1 ≤ N, M ≤ 11

输入样例：
1 2
1 3
1 4
2 2
2 3
2 4
2 11
4 11
0 0

输出样例：
1
0
1
2
3
5
144
51205
 */

/* 这个题有一定难度 */
//import java.util.*;
//
//public class Main {
//    // 定义常量，N表示行数的最大可能值，M表示状态数（2^N）
//    static final int N = 12, M = 1 << N;
//    // f[i][j]表示前i-1列已经摆好，且从i-1列伸到i列的状态是j的方案数
//    static long[][] f = new long[N][M];
//    // st[j]表示状态j是否有奇数个连续的0（无效状态）
//    static boolean[] st = new boolean[M];
//    // state[j]存储所有能与状态j合法配对的i-1列状态k
//    static List<List<Integer>> state = new ArrayList<>();
//
//    public static void main(String[] args) {
//        Scanner scanner = new Scanner(System.in);
//
//        // 初始化state列表
//        for (int i = 0; i < M; i++) {
//            state.add(new ArrayList<>());
//        }
//
//        while (true) {
//            int n = scanner.nextInt();
//            int m = scanner.nextInt();
//            if (n == 0 && m == 0) break;
//
//            // 第一部分预处理：检查每种状态是否有奇数个连续的0
//            for (int i = 0; i < (1 << n); i++) {
//                int cnt = 0; // 记录连续0的个数
//                boolean isValid = true; // 标记状态是否有效
//
//                for (int j = 0; j < n; j++) {
//                    // 检查i的第j位是否为1
//                    if ((i >> j & 1) == 1) {
//                        // 如果前面有奇数个0，则状态无效
//                        if ((cnt & 1) == 1) {
//                            isValid = false;
//                            break;
//                        }
//                        cnt = 0;
//                    } else {
//                        cnt++;
//                    }
//                }
//                // 检查最后一段连续的0
//                if ((cnt & 1) == 1) isValid = false;
//                st[i] = isValid;
//            }
//
//            // 第二部分预处理：检查i-1列和i列的状态是否冲突
//            for (int j = 0; j < (1 << n); j++) {
//                state.get(j).clear(); // 清空之前的状态
//
//                for (int k = 0; k < (1 << n); k++) {
//                    // 两列伸出的部分不能重叠(j & k == 0)
//                    // 且合并后的状态不能有奇数个连续的0(st[j | k])
//                    if ((j & k) == 0 && st[j | k]) {
//                        state.get(j).add(k);
//                    }
//                }
//            }
//
//            // 第三部分：DP过程
//            // 重置f数组
//            for (int i = 0; i < N; i++) {
//                Arrays.fill(f[i], 0);
//            }
//
//            // 初始状态：前-1列已经摆好，且没有伸到第0列的方案数为1
//            f[0][0] = 1;
//
//            // 遍历每一列
//            for (int i = 1; i <= m; i++) {
//                // 遍历当前列的所有可能状态
//                for (int j = 0; j < (1 << n); j++) {
//                    // 遍历能与j合法配对的所有i-1列状态k
//                    for (int k : state.get(j)) {
//                        f[i][j] += f[i - 1][k];
//                    }
//                }
//            }
//
//            // 输出结果：前m-1列已经摆好，且没有伸到第m列的所有方案数
//            System.out.println(f[m][0]);
//        }
//    }
//}

/*
给定一张n个点的带权无向图，点从0~n-1标号，求起点0到终点n-1的最短Hamilton路径。
Hamilton路径的定义是从0到n-1不重不漏地经过每个点恰好一次。

输入格式
第一行输入整数n。
接下来n行每行n个整数，其中第i行第j个整数表示点i到j的距离（记为a[i,j]）。
对于任意的x,y,z，数据保证a[x,x]=0并且a[x,y]=a[y,x]，并且a[x,y]+a[y,z]>=a[x,z]

输出格式
输出一个整数，表示最短Hamilton路径的长度。

数据范围
1≤n≤20
0≤a[i,j]≤10^7

输入样例：
5
0 2 4 5 1
2 0 6 5 3
4 6 0 8 3
5 5 8 0 5
1 3 3 5 0

输出样例：
18
 */

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[][] a = new int[n + 1][n + 1];
        int[][] dp = new int[1 << 20][20];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                a[i][j] = sc.nextInt();
            }
        }
        for (int[] row : dp) {
            Arrays.fill(row, 0x3f3f3f3f);
        }
        dp[1][0] = 0;//初始化,从0出发到0结束，路线状态表示为1
        for (int i = 0; i < (1 << n); i++) {
            for (int j = 0; j < n; j++) {
                if ((i >> j & 1) == 1) {
                    for (int k = 0; k < n; k++) {
                        if (((i - (1 << j)) >> k & 1) == 1) {
                            dp[i][j] = Math.min(dp[i][j], dp[i - (1 << j)][k] + a[k][j]);
                        }
                    }
                }
            }
        }
        System.out.println(dp[(1 << n) - 1][n - 1]);
    }
}



















